luogu2805 [NOI2009]植物大战僵尸 发表于 2018-04-11 123456789101112131415选某个植物就要选保护它的所有植物典型的最大权闭合子图愉快的打完了一测样例225?发现出现了一个环(良心样例不多见了)怎么去掉环呢tarjan?发现环连出去的点都相当于无敌的所以哪些点是可以被攻击的呢搜索!发现奇怪的性质。。这是topsort!愉快的拓扑一遍,然后重建边再dinic跑一遍 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153#include<bits/stdc++.h>#define mp make_pair#define pb push_backusing namespace std;typedef long long LL;typedef pair<int,int> PII;inline LL read(){ LL x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f;}const int N=608;int n,m;int v[N],d[N];int x,y,z;int s,t;int ans;inline int getid(int x,int y){ return (x-1)*m+y;}int nume,head[N],cur[N],headx[N];struct node{ int to,nxt,f;}e[N*N*4],ex[N*N];inline void addedge(int x,int y,int z){ e[++nume]=(node){y,head[x],z};head[x]=nume; e[++nume]=(node){x,head[y],0};head[y]=nume;}inline void insert(int x,int y){ ++d[y]; ex[++nume]=(node){y,headx[x]};headx[x]=nume;}bool del[N];int q[N],he,ta;inline void topsort(){ for(int i=1;i<=n*m;++i){ if(!d[i]) q[++ta]=i; else del[i]=1; } while(ta){ int x=q[ta];del[x]=0; --ta; for(int i=headx[x];i;i=ex[i].nxt){ --d[ex[i].to]; if(!d[ex[i].to]) q[++ta]=ex[i].to; } }}inline void rebuild(){ nume=1; s=0;t=n*m+1; for(int i=1;i<=n*m;++i){ if(!del[i]){ if(v[i]>0){ ans+=v[i]; addedge(s,i,v[i]); } else{ addedge(i,t,-v[i]); } for(int j=headx[i];j;j=ex[j].nxt){ if(!del[ex[j].to]){ addedge(ex[j].to,i,INT_MAX); } } } }}int dis[N];inline bool bfs(){ memset(dis,0,sizeof(dis)); he=1;ta=2; q[1]=s; dis[s]=1; while(he!=ta){ int x=q[he]; ++he; for(int i=head[x];i;i=e[i].nxt){ if(e[i].f&&!dis[e[i].to]){ dis[e[i].to]=dis[x]+1; if(e[i].to==t) return 1; q[ta]=e[i].to; ++ta; } } } return 0;}inline int dfs(int x,int low){ if(x==t||!low) return low; int flow=0,tmp; for(int i=head[x];i;i=e[i].nxt){ if(dis[e[i].to]==dis[x]+1&&(tmp=dfs(e[i].to,min(low,e[i].f)))){ flow+=tmp; low-=tmp; e[i].f-=tmp; e[i^1].f+=tmp; if(!low) return flow; } } if(low) dis[x]=0; return flow;}inline int dinic(){ int maxflow=0; while(bfs()){ for(int i=s;i<=t;++i){ cur[i]=head[i]; } maxflow+=dfs(s,INT_MAX); } return maxflow;}int main(){ n=read();m=read(); for(int i=1;i<=n;++i){ for(int j=1;j<=m;++j){ v[getid(i,j)]=read(); z=read(); while(z--){ x=read();y=read(); ++x;++y; insert(getid(i,j),getid(x,y)); } } } for(int i=1;i<=n;++i){ for(int j=2;j<=m;++j){ insert(getid(i,j),getid(i,j-1)); } } topsort(); rebuild(); ans-=dinic(); printf("%d",ans); return 0;}